#include "Comm.hpp"
#include "Log.hpp"

#include <cstring>
#include <cerrno>
#include <unistd.h>
// #include <stdio.h> //getline 用C++的

#include <iostream>
#include <string>

#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
const int RETRYTIMES = 5;
void Usage(const std::string &proc)
{
    std::cout << "格式：" << proc << " serverip serverport" << std::endl;
}

int VisitServer(const std::string &serverip, uint16_t serverport, int &sockfd)
{
    // 1.创建套接字
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd == -1)
    {
        lg.LogMessage(Fatal, "sockfd create falied, errno:%d, %s\n", errno, strerror(errno));
        return sockfd_err;
    }
    lg.LogMessage(Debug, "sockfd create succsee\n");

    // 2.1填写服务器信息
    struct sockaddr_in server;
    memset(&server, 0, sizeof server);
    server.sin_family = AF_INET;
    inet_pton(AF_INET, (const char *)serverip.c_str(), &server.sin_addr);
    server.sin_port = htons(serverport);
    // 2.2connect建立链接
    int ok = connect(sockfd, (struct sockaddr *)&server, sizeof server);
    if (ok == -1)
    {
        lg.LogMessage(Warning, "connect falied, errno:%d, %s\n", errno, strerror(errno));
        return connect_err;
    }
    lg.LogMessage(Debug, "connect success\n");

    std::cout << "输入需要的服务: ping translate transform" << std::endl;
    std::string str;
    getline(std::cin, str);
    write(sockfd, str.c_str(), str.size());

    if (str == "quit")
        return client_queit;
    getline(std::cin, str);

    int n = write(sockfd, str.c_str(), str.size());
    std::cout << "n:" << n << std::endl;

    if (n > 0)
    {
        char buffer[128] = {0}; // 这样的话，末尾添加0可以去掉
        int m = read(sockfd, buffer, sizeof buffer - 1);
        if (m > 0)
        {
            lg.LogMessage(Debug, "m: %d\n", m);
            // buffer[m] = 0;
            std::cout << buffer << std::endl;

            // for(int i = 0; i < m; i++)
            //     std::cout << i << ": "<<buffer[i] << std::endl;
        }
        else if (m == 0)
        {
            lg.LogMessage(Warning, "与服务器断开连接, errno: %d, %s\n", errno, strerror(errno));
            return connect_err;
        }
        else
        {
            lg.LogMessage(Error, "read错误, errno: %d, %s\n", errno, strerror(errno));
            return read_err;
        }
    }

    return 0;
}
int main(int argc, char *argv[])
{
    if (argc != 3)
    {
        Usage(argv[1]);
        return usage_err;
    }

    std::string serverip = argv[1];
    uint16_t port = std::stoi(argv[2]);
    int cnt = RETRYTIMES;
    while (cnt > 0)
    {
        int sockfd;
        int ok = VisitServer(serverip, port, sockfd);
        if (ok == client_queit)
        {
            close(sockfd);
            break;
        }
        else if (ok == connect_err || ok == read_err)
        {
            cnt--;
            std::cout << "connect retry...times:" << RETRYTIMES - cnt << std::endl;
            sleep(1);
        }
        else
            cnt = RETRYTIMES;
        close(sockfd);
    }
    if (cnt == 0)
        std::cout << "服务器断开" << std::endl;
    else
        std::cout << "正常退出" << std::endl;
    return 0;
}